package org.apache.harmony.javax.security.auth;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.DomainCombiner;
import java.security.Permission;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

public final class Subject
  implements Serializable
{
  private static final AuthPermission _AS = new AuthPermission("doAs");
  private static final AuthPermission _AS_PRIVILEGED = new AuthPermission("doAsPrivileged");
  private static final AuthPermission _PRINCIPALS;
  private static final AuthPermission _PRIVATE_CREDENTIALS;
  private static final AuthPermission _PUBLIC_CREDENTIALS;
  private static final AuthPermission _READ_ONLY;
  private static final AuthPermission _SUBJECT = new AuthPermission("getSubject");
  private static final long serialVersionUID = 3406440L;
  private final Set<Principal> principals;
  private transient SecureSet<Object> privateCredentials;
  private transient SecureSet<Object> publicCredentials;
  private boolean readOnly;

  static
  {
    _PRINCIPALS = new AuthPermission("modifyPrincipals");
    _PRIVATE_CREDENTIALS = new AuthPermission("modifyPrivateCredentials");
    _PUBLIC_CREDENTIALS = new AuthPermission("modifyPublicCredentials");
    _READ_ONLY = new AuthPermission("setReadOnly");
  }

  public Subject()
  {
    this.principals = new SecureSet(this, _PRINCIPALS);
    this.publicCredentials = new SecureSet(this, _PUBLIC_CREDENTIALS);
    this.privateCredentials = new SecureSet(this, _PRIVATE_CREDENTIALS);
    this.readOnly = false;
  }

  public Subject(boolean paramBoolean, Set<? extends Principal> paramSet, Set<?> paramSet1, Set<?> paramSet2)
  {
    if ((paramSet == null) || (paramSet1 == null) || (paramSet2 == null))
      throw new NullPointerException();
    this.principals = new SecureSet(this, _PRINCIPALS, paramSet);
    this.publicCredentials = new SecureSet(this, _PUBLIC_CREDENTIALS, paramSet1);
    this.privateCredentials = new SecureSet(this, _PRIVATE_CREDENTIALS, paramSet2);
    this.readOnly = paramBoolean;
  }

  private static void checkPermission(Permission paramPermission)
  {
    SecurityManager localSecurityManager = System.getSecurityManager();
    if (localSecurityManager != null)
      localSecurityManager.checkPermission(paramPermission);
  }

  private void checkState()
  {
    if (this.readOnly)
      throw new IllegalStateException("auth.0A");
  }

  public static Object doAs(Subject paramSubject, PrivilegedAction paramPrivilegedAction)
  {
    checkPermission(_AS);
    return doAs_PrivilegedAction(paramSubject, paramPrivilegedAction, AccessController.getContext());
  }

  public static Object doAs(Subject paramSubject, PrivilegedExceptionAction paramPrivilegedExceptionAction)
    throws PrivilegedActionException
  {
    checkPermission(_AS);
    return doAs_PrivilegedExceptionAction(paramSubject, paramPrivilegedExceptionAction, AccessController.getContext());
  }

  public static Object doAsPrivileged(Subject paramSubject, PrivilegedAction paramPrivilegedAction, AccessControlContext paramAccessControlContext)
  {
    Object localObject;
    checkPermission(_AS_PRIVILEGED);
    if (paramAccessControlContext == null)
      localObject = doAs_PrivilegedAction(paramSubject, paramPrivilegedAction, new AccessControlContext(new ProtectionDomain[0]));
    while (true)
    {
      return localObject;
      localObject = doAs_PrivilegedAction(paramSubject, paramPrivilegedAction, paramAccessControlContext);
    }
  }

  public static Object doAsPrivileged(Subject paramSubject, PrivilegedExceptionAction paramPrivilegedExceptionAction, AccessControlContext paramAccessControlContext)
    throws PrivilegedActionException
  {
    Object localObject;
    checkPermission(_AS_PRIVILEGED);
    if (paramAccessControlContext == null)
      localObject = doAs_PrivilegedExceptionAction(paramSubject, paramPrivilegedExceptionAction, new AccessControlContext(new ProtectionDomain[0]));
    while (true)
    {
      return localObject;
      localObject = doAs_PrivilegedExceptionAction(paramSubject, paramPrivilegedExceptionAction, paramAccessControlContext);
    }
  }

  private static Object doAs_PrivilegedAction(Subject paramSubject, PrivilegedAction paramPrivilegedAction, AccessControlContext paramAccessControlContext)
  {
    SubjectDomainCombiner localSubjectDomainCombiner;
    if (paramSubject == null)
      localSubjectDomainCombiner = null;
    while (true)
    {
      return AccessController.doPrivileged(paramPrivilegedAction, (AccessControlContext)AccessController.doPrivileged(new PrivilegedAction(paramAccessControlContext, localSubjectDomainCombiner)
      {
        public Object run()
        {
          return new AccessControlContext(this.val$context, this.val$combiner);
        }
      }));
      localSubjectDomainCombiner = new SubjectDomainCombiner(paramSubject);
    }
  }

  private static Object doAs_PrivilegedExceptionAction(Subject paramSubject, PrivilegedExceptionAction paramPrivilegedExceptionAction, AccessControlContext paramAccessControlContext)
    throws PrivilegedActionException
  {
    SubjectDomainCombiner localSubjectDomainCombiner;
    if (paramSubject == null)
      localSubjectDomainCombiner = null;
    while (true)
    {
      return AccessController.doPrivileged(paramPrivilegedExceptionAction, (AccessControlContext)AccessController.doPrivileged(new PrivilegedAction(paramAccessControlContext, localSubjectDomainCombiner)
      {
        public AccessControlContext run()
        {
          return new AccessControlContext(this.val$context, this.val$combiner);
        }
      }));
      localSubjectDomainCombiner = new SubjectDomainCombiner(paramSubject);
    }
  }

  public static Subject getSubject(AccessControlContext paramAccessControlContext)
  {
    Subject localSubject;
    checkPermission(_SUBJECT);
    if (paramAccessControlContext == null)
      throw new NullPointerException("auth.09");
    DomainCombiner localDomainCombiner = (DomainCombiner)AccessController.doPrivileged(new PrivilegedAction(paramAccessControlContext)
    {
      public DomainCombiner run()
      {
        return this.val$context.getDomainCombiner();
      }
    });
    if ((localDomainCombiner == null) || (!(localDomainCombiner instanceof SubjectDomainCombiner)))
      localSubject = null;
    while (true)
    {
      return localSubject;
      localSubject = ((SubjectDomainCombiner)localDomainCombiner).getSubject();
    }
  }

  private void readObject(ObjectInputStream paramObjectInputStream)
    throws IOException, ClassNotFoundException
  {
    paramObjectInputStream.defaultReadObject();
    this.publicCredentials = new SecureSet(this, _PUBLIC_CREDENTIALS);
    this.privateCredentials = new SecureSet(this, _PRIVATE_CREDENTIALS);
  }

  private void writeObject(ObjectOutputStream paramObjectOutputStream)
    throws IOException
  {
    paramObjectOutputStream.defaultWriteObject();
  }

  public boolean equals(Object paramObject)
  {
    int i;
    if (this == paramObject)
      i = 1;
    while (true)
    {
      while (true)
      {
        while (true)
        {
          return i;
          if ((paramObject != null) && (super.getClass() == paramObject.getClass()))
            break;
          i = 0;
        }
        Subject localSubject = (Subject)paramObject;
        if ((!(this.principals.equals(localSubject.principals))) || (!(this.publicCredentials.equals(localSubject.publicCredentials))) || (!(this.privateCredentials.equals(localSubject.privateCredentials))))
          break;
        i = 1;
      }
      i = 0;
    }
  }

  public Set<Principal> getPrincipals()
  {
    return this.principals;
  }

  public <T extends Principal> Set<T> getPrincipals(Class<T> paramClass)
  {
    return ((SecureSet)this.principals).get(paramClass);
  }

  public Set<Object> getPrivateCredentials()
  {
    return this.privateCredentials;
  }

  public <T> Set<T> getPrivateCredentials(Class<T> paramClass)
  {
    return this.privateCredentials.get(paramClass);
  }

  public Set<Object> getPublicCredentials()
  {
    return this.publicCredentials;
  }

  public <T> Set<T> getPublicCredentials(Class<T> paramClass)
  {
    return this.publicCredentials.get(paramClass);
  }

  public int hashCode()
  {
    return (this.principals.hashCode() + this.privateCredentials.hashCode() + this.publicCredentials.hashCode());
  }

  public boolean isReadOnly()
  {
    return this.readOnly;
  }

  public void setReadOnly()
  {
    checkPermission(_READ_ONLY);
    this.readOnly = true;
  }

  public String toString()
  {
    Iterator localIterator2;
    int i;
    Iterator localIterator3;
    StringBuilder localStringBuilder = new StringBuilder("Subject:\n");
    Iterator localIterator1 = this.principals.iterator();
    if (!(localIterator1.hasNext()))
    {
      localIterator2 = this.publicCredentials.iterator();
      if (localIterator2.hasNext())
        break label112;
      i = localStringBuilder.length() - 1;
      localIterator3 = this.privateCredentials.iterator();
    }
    try
    {
      while (true)
      {
        while (true)
        {
          boolean bool = localIterator3.hasNext();
          if (bool)
            break label142;
          return localStringBuilder.toString();
          localStringBuilder.append("\tPrincipal: ");
          localStringBuilder.append(localIterator1.next());
          localStringBuilder.append('\n');
        }
        label112: localStringBuilder.append("\tPublic Credential: ");
        localStringBuilder.append(localIterator2.next());
        localStringBuilder.append('\n');
      }
      label142: localStringBuilder.append("\tPrivate Credential: ");
      localStringBuilder.append(localIterator3.next());
      localStringBuilder.append('\n');
    }
    catch (SecurityException localSecurityException)
    {
      while (true)
      {
        localStringBuilder.delete(i, localStringBuilder.length());
        localStringBuilder.append("\tPrivate Credentials: no accessible information\n");
      }
    }
  }

  private final class SecureSet<SST> extends AbstractSet<SST>
  implements Serializable
  {
    private static final int SET_Principal = 0;
    private static final int SET_PrivCred = 1;
    private static final int SET_PubCred = 2;
    private static final long serialVersionUID = 391478823L;
    private LinkedList<SST> elements;
    private transient AuthPermission permission;
    private int setType;

    protected SecureSet(, AuthPermission paramAuthPermission)
    {
      this.permission = paramAuthPermission;
      this.elements = new LinkedList();
    }

    protected SecureSet(, Collection<? extends SST> paramCollection)
    {
      this(paramAuthPermission, paramCollection);
      if (localObject1.getClass().getClassLoader() == null)
      {
        i = 1;
        localIterator = localObject1.iterator();
      }
      while (true)
      {
        Object localObject2;
        do
        {
          while (!(localIterator.hasNext()))
          {
            return;
            i = 0;
          }
          localObject2 = localIterator.next();
          verifyElement(localObject2);
        }
        while ((i == 0) && (this.elements.contains(localObject2)));
        this.elements.add(localObject2);
      }
    }

    private void readObject()
      throws IOException, ClassNotFoundException
    {
      Iterator localIterator;
      paramObjectInputStream.defaultReadObject();
      switch (this.setType)
      {
      default:
        throw new IllegalArgumentException();
      case 0:
        this.permission = Subject.access$2();
        localIterator = this.elements.iterator();
      case 1:
      case 2:
      }
      while (true)
      {
        while (true)
        {
          while (true)
          {
            if (localIterator.hasNext())
              break label89;
            return;
            this.permission = Subject.access$3();
          }
          this.permission = Subject.access$5();
        }
        label89: verifyElement(localIterator.next());
      }
    }

    private void verifyElement()
    {
      if (paramObject == null)
        throw new NullPointerException();
      if ((this.permission == Subject.access$2()) && (!(Principal.class.isAssignableFrom(paramObject.getClass()))))
        throw new IllegalArgumentException("auth.0B");
    }

    private void writeObject()
      throws IOException
    {
      Iterator localIterator;
      if (this.permission == Subject.access$3())
      {
        localIterator = iterator();
        if (!(localIterator.hasNext()))
          this.setType = 1;
      }
      while (true)
      {
        while (true)
        {
          while (true)
          {
            paramObjectOutputStream.defaultWriteObject();
            return;
            localIterator.next();
          }
          if (this.permission != Subject.access$2())
            break;
          this.setType = 0;
        }
        this.setType = 2;
      }
    }

    public boolean add()
    {
      int i;
      verifyElement(paramSST);
      Subject.access$0(this.this$0);
      Subject.access$1(this.permission);
      if (!(this.elements.contains(paramSST)))
      {
        this.elements.add(paramSST);
        i = 1;
      }
      while (true)
      {
        return i;
        i = 0;
      }
    }

    protected final <E> Set<E> get()
    {
      if (paramClass == null)
        throw new NullPointerException();
      2 local2 = new AbstractSet(this, paramClass)
      {
        private LinkedList<E> elements = new LinkedList();

        public boolean add()
        {
          int i;
          if (!(this.val$c.isAssignableFrom(paramE.getClass())))
            throw new IllegalArgumentException("auth.0C " + this.val$c.getName());
          if (this.elements.contains(paramE))
            i = 0;
          while (true)
          {
            return i;
            this.elements.add(paramE);
            i = 1;
          }
        }

        public Iterator<E> iterator()
        {
          return this.elements.iterator();
        }

        public boolean retainAll()
        {
          if (paramCollection == null)
            throw new NullPointerException();
          return super.retainAll(paramCollection);
        }

        public int size()
        {
          return this.elements.size();
        }
      };
      Iterator localIterator = iterator();
      while (true)
      {
        Object localObject;
        do
        {
          if (!(localIterator.hasNext()))
            return local2;
          localObject = localIterator.next();
        }
        while (!(paramClass.isAssignableFrom(localObject.getClass())));
        local2.add(paramClass.cast(localObject));
      }
    }

    public Iterator<SST> iterator()
    {
      Object localObject;
      if (this.permission == Subject.access$3())
        localObject = new SecureIterator(this, this.elements.iterator())
        {
          public SST next()
          {
            Object localObject = this.iterator.next();
            Subject.access$1(new PrivateCredentialPermission(localObject.getClass().getName(), Subject.access$4(Subject.SecureSet.access$1(this.this$1))));
            return localObject;
          }
        };
      while (true)
      {
        return localObject;
        localObject = new SecureIterator(this, this.elements.iterator());
      }
    }

    public boolean retainAll()
    {
      if (paramCollection == null)
        throw new NullPointerException();
      return super.retainAll(paramCollection);
    }

    public int size()
    {
      return this.elements.size();
    }

    private class SecureIterator
  implements Iterator<SST>
    {
      protected Iterator<SST> iterator;

      protected SecureIterator()
      {
        this.iterator = localObject;
      }

      public boolean hasNext()
      {
        return this.iterator.hasNext();
      }

      public SST next()
      {
        return this.iterator.next();
      }

      public void remove()
      {
        Subject.access$0(Subject.SecureSet.access$1(this.this$1));
        Subject.access$1(Subject.SecureSet.access$0(this.this$1));
        this.iterator.remove();
      }
    }
  }
}